package com.hmdp.listener;

import com.hmdp.dto.Result;
import com.hmdp.entity.VoucherOrder;
import com.hmdp.service.ISeckillVoucherService;
import com.hmdp.service.IVoucherOrderService;
import com.hmdp.service.impl.SeckillVoucherServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Component
@Slf4j
public class SeckillListener {

    @Resource
    private ISeckillVoucherService seckillVoucherService;
    @Resource
    private IVoucherOrderService voucherOrderService;
    private static final ExecutorService SECKILL_ORDER_EXECUTOR = Executors.newFixedThreadPool(10);
    private class SeckillOrderTask implements Runnable {

        private final VoucherOrder voucherOrder;


        SeckillOrderTask(VoucherOrder voucherOrder) {
            this.voucherOrder = voucherOrder;
        }

        /**
         *    处理秒杀订单逻辑
         */
        @Transactional
        public void run () {
            //扣减库存
            boolean success = seckillVoucherService.update()
                    .setSql("stock = stock - 1") // set stock = stock - 1
                    .eq("voucher_id", voucherOrder.getVoucherId())
                    .gt("stock", 0) // where id = ? and stock > 0
                    .update();
            if (!success) {
                // 扣减失败
                log.info("数据库扣减秒杀卷订单失败");
            }

            //保存订单
            voucherOrderService.save(voucherOrder);

        }
    };


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "seckill.order.queue"),
            exchange = @Exchange(name = "seckill.order.exchange", type = ExchangeTypes.TOPIC),
            key = "seckill.order"
    ))
    public void listenTopicQueue(VoucherOrder msg) {
        SECKILL_ORDER_EXECUTOR.submit(new SeckillOrderTask(msg));
    }

}
